package com.cuixichang.minimalism.domain;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cuixichang.minimalism.acl.PlugDesign;
import com.cuixichang.minimalism.acl.PlugDesignComponent;
import com.cuixichang.minimalism.acl.SubassemblyDesignAbs;
import com.cuixichang.minimalism.basal.base.Validate;
import com.cuixichang.minimalism.basal.core.RelationDict;
import com.cuixichang.minimalism.basal.enums.DefaultNumberEnum;
import com.cuixichang.minimalism.basal.enums.SubassemblyTypeEnum;
import com.cuixichang.minimalism.core.mybatis.cnstants.BaseFieldNames;
import com.cuixichang.minimalism.core.security.userdetails.CredentialDetail;
import com.cuixichang.minimalism.mapper.IFormMapper;
import com.cuixichang.minimalism.mapper.IFormPlugMapper;
import com.cuixichang.minimalism.mapper.IFormValueMapper;
import com.cuixichang.minimalism.service.IFormPlugService;
import com.cuixichang.minimalism.service.IFormService;
import com.cuixichang.minimalism.service.IFormValueService;
import com.cuixichang.minimalism.transfer.dto.IFormDTO;
import com.cuixichang.minimalism.transfer.dto.IFormPlugDTO;
import com.cuixichang.minimalism.transfer.dto.IFormValueDTO;
import com.cuixichang.minimalism.transfer.po.IForm;
import com.cuixichang.minimalism.transfer.po.IFormPlug;
import com.cuixichang.minimalism.transfer.po.IFormValue;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class IFormCommandServiceImpl implements IFormCommandService{
    @Autowired
    private IFormMapper iFormMapper;
    @Autowired
    private IFormService iFormService;
    @Autowired
    private IFormPlugService iFormPlugService;
    @Autowired
    private IFormPlugMapper iFormPlugMapper;
    @Autowired
    private List<SubassemblyDesignAbs> subassemblyDesigns;
    @Autowired
    private IFormValueService formValueService;
    @Autowired
    private IFormValueMapper iFormValueMapper;
    @Override
    public List<String> getFormModules(String systemCode) {
        Assert.hasText(systemCode,"系统编码不能为空");
        List<IForm> result = iFormMapper.selectList(new QueryWrapper<IForm>()
                .select("DISTINCT module_name").eq("create_system_code", systemCode));
        if(CollectionUtils.isEmpty(result)) return Collections.singletonList("user");;
        return result.stream().map(IForm::getModuleName).collect(Collectors.toList());
    }

    @Override
    public IFormDTO insert(IFormDTO dto,CredentialDetail credentialDetail) {
        List<String> checkPlugs = dto.getCheckPlugs();
        dto.setCreateLoginId(Objects.nonNull(credentialDetail)? credentialDetail.getLoginId(): DefaultNumberEnum.Zero.getCode());
        IFormDTO iform = iFormService.insertHasOption(dto, temp -> {
            Optional<SubassemblyDesignAbs> first = subassemblyDesigns.stream().filter(subassemblyDesignAbs ->
                    subassemblyDesignAbs.getType().getKey().equals(temp.getFieldType())).findFirst();
            Assert.isTrue(first.isPresent(), "不支持该类型字段");
            SubassemblyDesignAbs subassemblyDesignAbs = first.get();
            Validate validate = subassemblyDesignAbs.structureValidate(temp.getLimitValue());
            String message = Optional.ofNullable(validate).filter(check -> !check.getChecked())
                    .map(Validate::getMessage).orElse(StrUtil.EMPTY);
            Assert.isTrue(StrUtil.isBlank(message) , message);
            if(!CollectionUtils.isEmpty(checkPlugs)){
                List<RelationDict> applicationPlug = subassemblyDesignAbs.getApplicationPlug(
                        temp.getCreateSystemCode(), temp.getModuleName(), temp.getFieldType());
                List<String> allowUsePlugs = applicationPlug.stream().map(RelationDict::getKey).collect(Collectors.toList());
                Assert.isTrue(checkPlugs.stream().allMatch(allowUsePlugs::contains), "插件不存在或已绑定");
            }
            return null;
        });
        if(!CollectionUtils.isEmpty(checkPlugs)){
            List<String> plugs = checkPlugs.stream().map(plugName -> iFormPlugService.insert(
                    IFormPlugDTO.builder().formId(iform.getId()).fieldType(iform.getFieldType())
                    .plugName(plugName).moduleName(iform.getModuleName()).createSystemCode(iform.getCreateSystemCode())
                    .createLoginId(dto.getCreateLoginId()).build())).map(IFormPlugDTO::getPlugName).collect(Collectors.toList());
            iform.setCheckPlugs(plugs);
        }
        return iform;
    }

    @Override
    public Page<IFormDTO> searchPageByConditional(IFormDTO dto, Long pageNo, Long pageSize) {
        Assert.notNull(dto,"参数为空,请检查");
        Assert.notNull(pageNo,"页码不能为空");
        Assert.notNull(pageSize,"每页数量不能为空");
        Page<IFormDTO> result = iFormService.selectPage(dto, pageSize, pageNo, (menu, queryWrapper)-> {
            String keyword = dto.getKeyword();
            if (StrUtil.isNotBlank(keyword)) {
                queryWrapper.and(warp -> {
                    warp.like("field_name", keyword).or().like("field_code", keyword);
                });
            }
        });
        List<IFormDTO> records = result.getRecords();
        if(!CollectionUtils.isEmpty(records)){
            records.forEach(record->{
                List<IFormPlugDTO> iFormPlugDTOS = iFormPlugService.selectList(IFormPlugDTO.builder()
                        .formId(record.getId()).fieldType(record.getFieldType()).moduleName(record.getModuleName())
                        .createSystemCode(record.getCreateSystemCode()).build());
                if(!CollectionUtils.isEmpty(iFormPlugDTOS)){
                    record.setCheckPlugs(iFormPlugDTOS.stream().map(IFormPlugDTO::getPlugName).distinct()
                            .collect(Collectors.toList()));
                }
            });
        }
        return result;
    }

    @Override
    public boolean deleteById(Long id, String systemCode) {
        Assert.notNull(id,"表单Id不能为空");
        Assert.hasText(systemCode,"系统编码不能为空");
        IFormDTO iForm = iFormService.selectOne(IFormDTO.builder().id(id).createSystemCode(systemCode).build());
        if(Objects.nonNull(iForm)){
             iFormPlugService.deleteByCondition(IFormPlugDTO.builder().createSystemCode(iForm.getCreateSystemCode())
                     .moduleName(iForm.getModuleName()).fieldType(iForm.getFieldType()).formId(id).build());
            List<IFormValue> iFormValues = iFormValueMapper.selectList(new QueryWrapper<IFormValue>().select("group_id").
                    eq("create_system_code", iForm.getCreateSystemCode()).eq("form_id", id)
                    .eq("module_name", iForm.getModuleName()));
            if(!CollectionUtils.isEmpty(iFormValues)){
                formValueService.deleteByCondition(IFormValueDTO.builder().createSystemCode(iForm.getCreateSystemCode())
                        .moduleName(iForm.getModuleName()).formId(id).build(),(formValue, queryWrapper)->{
                    queryWrapper.in("group_id", iFormValues.stream().map(IFormValue::getGroupId).collect(Collectors.toList()));
                });
            }
            return iFormService.deleteById(id) == 1;
        }
        return false;
    }

    @Override
    public IFormDTO selectByIdHasPreCheck(Long id, String systemCode) {
        Assert.notNull(id,"表单字段配置ID为空,请检查");
        Assert.hasText(systemCode,"系统编码不能为空");
        IFormDTO record = iFormService.selectOne(IFormDTO.builder().id(id).createSystemCode(systemCode).build());
        if(Objects.nonNull(record)){
            List<IFormPlugDTO> iFormPlugDTOS = iFormPlugService.selectList(IFormPlugDTO.builder()
                    .formId(record.getId()).fieldType(record.getFieldType()).moduleName(record.getModuleName())
                    .createSystemCode(record.getCreateSystemCode()).build());
            if(!CollectionUtils.isEmpty(iFormPlugDTOS)){
                record.setCheckPlugs(iFormPlugDTOS.stream().map(IFormPlugDTO::getPlugName).distinct()
                        .collect(Collectors.toList()));
            }
        }
        return record;
    }

    @Override
    public boolean updateById(IFormDTO dto, CredentialDetail credentialDetail) {
        Assert.notNull(dto,"参数为空,请检查");
        Long id = dto.getId();
        Assert.notNull(id,"表单字段Id不能为空");
        String createSystemCode = dto.getCreateSystemCode();
        Assert.hasText(createSystemCode,"系统编码不能为空");
        String moduleName = dto.getModuleName();
        Assert.hasText(moduleName,"模块名称不能为空");
        dto.setCreateLoginId(Objects.nonNull(credentialDetail)? credentialDetail.getLoginId(): DefaultNumberEnum.Zero.getCode());
        return iFormService.updateById(dto, (form, queryWrapper) -> {
            String fieldType = form.getFieldType();
            if(StrUtil.isNotBlank(fieldType)){
              Optional<SubassemblyDesignAbs> first = subassemblyDesigns.stream().filter(subassemblyDesignAbs ->
                    subassemblyDesignAbs.getType().getKey().equals(fieldType)).findFirst();
                Assert.isTrue(first.isPresent(), "不支持该类型字段");
                SubassemblyDesignAbs subassemblyDesignAbs = first.get();
                Validate validate = subassemblyDesignAbs.structureValidate(form.getLimitValue());
                String message = Optional.ofNullable(validate).filter(check -> !check.getChecked())
                    .map(Validate::getMessage).orElse(StrUtil.EMPTY);
                Assert.isTrue(StrUtil.isBlank(message) , message);
                List<String> checkPlugs = dto.getCheckPlugs();
                if(!CollectionUtils.isEmpty(checkPlugs)){
                    IFormPlugDTO selectCondition = IFormPlugDTO.builder().fieldType(fieldType)
                            .moduleName(moduleName).createSystemCode(createSystemCode).build();
                    List<IFormPlugDTO> iFormPlugDTOS = iFormPlugService.selectList(selectCondition);
                    List<RelationDict> applicationBindingPlug = subassemblyDesignAbs.getApplicationBindingPlug(iFormPlugDTOS, id);
                    List<String> allowPlugs = applicationBindingPlug.stream().map(RelationDict::getKey).collect(Collectors.toList());
                    Assert.isTrue(checkPlugs.stream().allMatch(allowPlugs::contains), "插件不存在或已绑定");
                    List<IFormPlugDTO> storys = iFormPlugDTOS.stream().filter(plug -> plug.getFormId().equals(id)).collect(Collectors.toList());
                    // 过滤已取消的插件
                    List<Long> needCancelPlugs = storys.stream().filter(plug -> !checkPlugs.contains(plug.getPlugName()))
                            .map(IFormPlugDTO::getId).collect(Collectors.toList());
                    if(!CollectionUtils.isEmpty(needCancelPlugs)){
                        iFormPlugService.deleteByIds(needCancelPlugs);
                    }
                    // 绑定插件
                    checkPlugs.forEach(plugName->{
                        IFormPlugDTO build = IFormPlugDTO.builder().formId(id).fieldType(fieldType).plugName(plugName)
                                .moduleName(moduleName).createSystemCode(createSystemCode).createLoginId(dto.getCreateLoginId()).build();
                        iFormPlugService.insertHasOption(build, iFormPlugDTO -> storys.stream().filter(tempDto -> tempDto.getPlugName().equals(plugName))
                                .findFirst().orElse(null));
                    });
                }else {
                    IFormPlugDTO deleteCondition = IFormPlugDTO.builder().formId(id).fieldType(fieldType)
                            .moduleName(moduleName).createSystemCode(createSystemCode).build();
                    iFormPlugService.deleteByCondition(deleteCondition);
                }
            }
        }) == 1;
    }

    @Override
    public List<IFormDTO> searchFieldsByModuleName(IFormDTO dto,Long loginId) {
        Assert.notNull(dto,"参数为空,请检查");
        String systemCode = dto.getCreateSystemCode();
        Assert.hasText(systemCode,"系统编码不能为空");
        String moduleName = dto.getModuleName();
        Assert.hasText(moduleName,"模块名称不能为空");
        Map<String, List<String>> plugNames = subassemblyDesigns.stream().map(SubassemblyDesignAbs::getType)
                .collect(Collectors.toMap(SubassemblyTypeEnum::getKey, subassemblyTypeEnum -> {
            List<PlugDesign> plugDesign = PlugDesignComponent.getPlugDesign(subassemblyTypeEnum);
            return CollectionUtils.isEmpty(plugDesign)?Collections.emptyList():
                        plugDesign.stream().map(PlugDesign::plugName).collect(Collectors.toList());
        }));

        if(CollectionUtils.isEmpty(plugNames)) return Collections.emptyList();
        return iFormService.selectList(dto, (form, queryWrapper) -> {
                queryWrapper.in("field_type",plugNames.keySet());
                List<Long> ignoIds = new ArrayList<>();
                // 需要隐藏的插件
                List<IFormPlug> iFormPlugs = Collections.emptyList();
                List<String> hiddenTypes = subassemblyDesigns.stream().map(SubassemblyDesignAbs::getType).filter(design -> {
                  List<PlugDesign> plugDesign = PlugDesignComponent.getPlugDesign(design);
                  if (!CollectionUtils.isEmpty(plugDesign)) {
                      Optional<PlugDesign> hiddenOption = plugDesign.stream().filter(PlugDesign::hidden).findFirst();
                      return hiddenOption.isPresent();
                  }
                  return false;
               }).map(SubassemblyTypeEnum::getKey).collect(Collectors.toList());
               if(!CollectionUtils.isEmpty(hiddenTypes)){
                   iFormPlugs= iFormPlugMapper.selectList(new QueryWrapper<IFormPlug>().select("form_id")
                      .eq("create_system_code", systemCode).eq("module_name", moduleName)
                           .in("field_type", hiddenTypes));
               }

               if(!CollectionUtils.isEmpty(iFormPlugs)){
                   if(Objects.nonNull(dto.getAllowDesign())){
                        ignoIds.addAll(iFormPlugs.stream().map(IFormPlug::getFormId).collect(Collectors.toList()));
                    }

                    if(Objects.nonNull(loginId)){
                        List<IFormPlug> finalIFormPlugs = iFormPlugs;
                        List<IFormValueDTO> stores = formValueService.selectList(IFormValueDTO.builder().createSystemCode(systemCode).moduleName(moduleName)
                                .groupId(String.valueOf(loginId)).build(), (po, formValueQueryWrapper) -> {
                            formValueQueryWrapper.in("form_id", finalIFormPlugs.stream().map(IFormPlug::getFormId)
                                    .collect(Collectors.toList()));
                        });
                        if(!CollectionUtils.isEmpty(stores)){
                            ignoIds.addAll(stores.stream().map(IFormValueDTO::getFormId).collect(Collectors.toList()));
                        }
                    }
               }
                queryWrapper.notIn(!CollectionUtils.isEmpty(ignoIds), BaseFieldNames.ID,ignoIds.stream().distinct()
                        .collect(Collectors.toList()));
        }).stream().peek(form->form.setCheckPlugs(plugNames.get(form.getFieldType()))).collect(Collectors.toList());
    }
}
